<template>
  <div class="user-header">
    <div class="buttonTop">
      <el-button type="primary" @click="handleAdd">+新增</el-button>
      <el-button type="danger" @click="handleDelList" style="padding: 5px"
        >批量删除</el-button
      >
    </div>
    <el-form :inline="true" :model="roleFormInline" class="ef_1">
      <el-form-item>
        <el-input
          v-model="roleFormInline.keywords"
          placeholder="请输入角色名检索"
          clearable
          prefix-icon="Search"
          class="ei_1"
          style="width: 190px"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleSearch">搜索</el-button>
      </el-form-item>
    </el-form>
  </div>
  <!-- 表格数据 -->
  <div class="table">
    <el-table
      :data="RoleTableData"
      style="width: 100%; height: 494px"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="30" />
      <el-table-column
        type="index"
        label="角色编号"
        align="center"
        width="100"
      ></el-table-column>
      <el-table-column
        v-for="item in menuTableLabel"
        align="center"
        :key="item.prop"
        :prop="item.prop"
        :label="item.label"
        :width="item.width ? item.width : 125"
      />
      <el-table-column label="启用" prop="enable" width="70">
        <template #default="{ row }">
          <el-switch
            v-model="row.enable"
            inline-prompt
            inactive-color="#f56c6c"
            active-text="是"
            inactive-text="否"
            @change="changeRoleStatus(row)"
          />
        </template>
      </el-table-column>
      <el-table-column
        label="创建时间"
        prop="createTime"
        align="center"
        width="150"
        :show-overflow-tooltip="true"
      >
      </el-table-column>
      <el-table-column
        label="创建人"
        :show-overflow-tooltip="true"
        prop="createBy"
        align="center"
        width="90"
      >
      </el-table-column>
      <el-table-column fixed="right" align="center" label="操作" width="300">
        <template #default="scope">
          <el-button
            link
            type="primary"
            icon="Edit"
            v-if="scope.row.description != 'superAdmin'"
            @click="handleEdit(scope.row)"
            v-hasPermi="['system:role:edit']"
            >编辑</el-button
          >
          <el-button
            link
            type="danger"
            icon="Delete"
            v-if="scope.row.description != 'superAdmin'"
            @click="handleRemove(scope.row)"
            v-hasPermi="['system:role:remove']"
            >删除</el-button
          >
          <el-button
            link
            type="primary"
            icon="CircleCheck"
            v-if="scope.row.description != 'superAdmin'"
            @click="handleDataScope(scope.row)"
            v-hasPermi="['system:role:edit']"
            >菜单权限</el-button
          >
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <el-pagination
      small
      background
      layout="prev, pager, next"
      :total="config.total"
      class="pager mt-5"
      @current-change="handleCurrentPageChange"
    />
  </div>
  <!--新增和编辑用户 dialogVisible：隐藏显示对话框视图 -->
  <Dialog
    :dialogVisible="dialogVisible"
    :action="getAction.action"
    :rowInfo="rowInfo"
    @CloseDialog="CloseDialog"
    @resetGetRoleData="resetGetRoleData"
  ></Dialog>

  <!-- 角色菜单弹框 -->
  <el-dialog title="角色权限分配" v-model="showRoleScope" width="500px">
    <el-form :model="form" label-width="80px" ref="roleMenuForm">
      <el-form-item label="菜单搜索">
        <el-input
          placeholder="请输入关键字进行过滤"
          v-model="searchText"
        ></el-input>
      </el-form-item>
      <el-form-item label="权限字符">
        <el-input v-model="form.roleKey" :disabled="true"></el-input>
      </el-form-item>
      <el-form-item label="菜单权限">
        <el-checkbox
          v-model="form.menuExpand"
          @change="handleCheckedTreeExpand($event, 'menu')"
          >展开/折叠</el-checkbox
        >
        <el-checkbox
          v-model="menuNodeAll"
          @change="handleCheckedTreeNodeAll($event, 'menu')"
          >全选/全不选</el-checkbox
        >
        <el-checkbox
          v-model="form.menuCheckStrictly"
          @change="handleCheckedTreeConnect($event, 'menu')"
          >父子联动</el-checkbox
        >
        <el-tree
          class="tree-border"
          :data="menuOptions"
          show-checkbox
          ref="menu"
          node-key="id"
          :check-strictly="!form.menuCheckStrictly"
          empty-text="加载中，请稍后"
          :filter-node-method="menuFilterNode"
          :props="defaultProps"
          default-expand-all="true"
        ></el-tree>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button type="primary" @click="submitRoleScope()">保存</el-button>
      <el-button @click="roleMenuCancel()">取 消</el-button>
    </div>
  </el-dialog>
</template>
<script setup>
import {
  defineComponent,
  getCurrentInstance,
  nextTick,
  onMounted,
  reactive,
  ref,
  watch,
} from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import Dialog from "./components/Dialog.vue";
import { rest } from "underscore";
const { proxy } = getCurrentInstance();
//  查询角色、分页、搜索角色
const config = reactive({
  total: 0,
  page: 1,
  size: 10,
  roleName: "",
});

// 双向绑定，为了关键词搜索
const roleFormInline = reactive({
  keywords: "",
});
// 表格列配置
const menuTableLabel = reactive([
  { label: "角色名称", prop: "name" },
  { label: "权限字符", prop: "description" },
  { label: "显示顺序", prop: "roleSort" },
]);

// 用于子组件重置查询表格
const resetGetRoleData = () => {
  getRoleData(config);
};
// 表格数据
const RoleTableData = ref();
onMounted(() => {
  getRoleData(config);
});
// 获取角色数据
const getRoleData = async (config) => {
  let res = await proxy.$api.role.getRoleData(config);
  if (res) {
    config.total = res.data.total;
    if (res.data.dataList !== null && res.data.dataList.length !== 0) {
      RoleTableData.value = res.data.dataList.map((item) => {
        item.enable = item.enable === 1 ? true : false;
        return item;
      });
    }
  }
};
// 页面跳转，触发分页条件查询
const handleCurrentPageChange = (page) => {
  config.page = page;
  getUserData(config);
};

//改变角色状态（是否禁用）
const changeRoleStatus = (row) => {
  let status = row.enable === true ? "启用" : "禁用";
  ElMessageBox.confirm(
    `确定要 "${status}"  角色 "${row.name}" 吗?`,
    "系统提示",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }
  )
    .then(async () => {
      const id = row.id;
      const enable = row.enable === true ? 1 : 0;
      let res = await proxy.$api.role.changeRoleEnable({
        id,
        enable,
      });
      if (res) {
        ElMessage({
          type: "success",
          message: `用户 "${row.name}" 状态已修改为 "${status}"`,
        });
        getRoleData(config);
      }
    })
    .catch(() => {
      row.enable = row.enable === true ? false : true;
    });
};

// 关键词搜索
const handleSearch = () => {
  config.roleName = roleFormInline.keywords;
  getRoleData(config);
};

const dialogVisible = ref();
const rowInfo = ref();
// 复用模态框,新增和编辑
const getAction = reactive({
  action: "add",
});
// 新增按钮
const handleAdd = () => {
  getAction.action = "add";
  dialogVisible.value = true;
};
// 编辑按钮
const handleEdit = (row) => {
  getAction.action = "edit";
  // 将值设置为 null 以触发 watcher
  rowInfo.value = null;
  // 使用 $nextTick 确保在下一个 DOM 更新周期再设置正确的值
  nextTick(() => {
    rowInfo.value = row;
  });
  dialogVisible.value = true;
};

// 子组件弹框关闭
const CloseDialog = () => {
  dialogVisible.value = false;
};

// 删除菜单
const handleRemove = (row) => {
  ElMessageBox.confirm("确定要删除吗", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      // 删除操作
      let res = await proxy.$api.role.deleteRole({ id: row.id });
      if (res) {
        ElMessage({
          showClose: true,
          message: res.data,
          type: "success",
        });
        getRoleData(config);
      }
    })
    .catch(() => {
      // catch error
    });
};
let ids = reactive([]);
// 批量选中
const handleSelectionChange = (val) => {
  ids = [];
  val.forEach((item) => {
    ids.push(item.id);
  });
};
// 批量删除
const handleDelList = () => {
  ElMessageBox.confirm("确定要删除吗", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      if (ids.length !== 0) {
        let res = await proxy.$api.role.batchDelRole(ids);
        if (res) {
          ElMessage({
            showClose: true,
            message: res.data,
            type: "success",
          });
          getRoleData(config);
          ids = [];
        }
      } else {
        ElMessage({
          showClose: true,
          message: "请选择要删除的用户",
          type: "warning",
        });
      }
    })
    .catch((err) => {});
};

const form = reactive({
  roleId: "",
  roleName: "",
  roleKey: "",
  menuCheckStrictly: true,
  menuExpand: true,
});
const showRoleScope = ref();

// 树形控件获取菜单数据信息
const handleDataScope = async (row) => {
  console.log(
    "%c [ row ]-373",
    "font-size:13px; background:pink; color:#bf2c9f;",
    row
  );

  reset();
  showRoleScope.value = true;
  const roleId = row.id;
  const roleMenu = getRoleMenuTreeselect(roleId);
  // 选中当前角色拥有的菜单权限
  roleMenu.then((res) => {
    const checkedKeys = res.data.checkKeys;
    checkedKeys.forEach((v) => {
      nextTick(() => {
        proxy.$refs.menu.setChecked(v, true, false);
      });
    });
  });
  form.roleId = row.id;
  // form.roleName = row.description;
  form.roleKey = row.description;
};
// 取消按钮
const roleMenuCancel = () => {
  showRoleScope.value = false;
  reset();
  proxy.$refs.roleMenuForm.resetFields();
};

// 树形数据
const menuOptions = ref();
/** 根据角色ID查询菜单树结构 */
const getRoleMenuTreeselect = async (roleId) => {
  let res = await proxy.$api.menu.getMenuTreeSelect({ roleId });
  if (res) {
    console.log(
      "%c [ res ]-421",
      "font-size:13px; background:pink; color:#bf2c9f;",
      res
    );
    menuOptions.value = res.data.menus.map((item) => {
      return item;
    });
  }
  return res;
};

// 菜单筛选过滤
const searchText = ref();
watch(searchText, (newValue) => {
  proxy.$refs.menu.filter(newValue);
});
// 菜单筛选
const menuFilterNode = (value, data) => {
  if (!value) return true;
  return data.label.indexOf(value) !== -1;
};

const reset = () => {
  form.value = {
    roleId: "",
    roleName: "",
    roleKey: "",
    menuCheckStrictly: true,
    menuExpand: true,
  };
};

// 树权限（全选/全不选）
const handleCheckedTreeNodeAll = (value, type) => {
  if (type == "menu") {
    proxy.$refs.menu.setCheckedNodes(value ? menuOptions.value : []);
  }
};
// 树权限（父子联动）
const handleCheckedTreeConnect = (value, type) => {
  if (type == "menu") {
    form.menuCheckStrictly = value;
  }
};

// 树权限（展开/折叠）
const handleCheckedTreeExpand = (value, type) => {
  if (type == "menu") {
    const treeList = menuOptions.value;
    for (let i = 0; i < treeList.length; i++) {
      proxy.$refs.menu.store.nodesMap[treeList[i].id].expanded = value;
    }
  }
};

const submitRoleScope = async () => {
  if (form.roleId != undefined) {
    let checkedKeys = proxy.$refs.menu.getCheckedKeys();
    let halfCheckedKeys = proxy.$refs.menu.getHalfCheckedKeys();
    checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);

    let params = {
      roleId: form.roleId,
      menuIds: checkedKeys,
    };
    let res = await proxy.$api.role.updataRoleMenuScope(params);
    if (res) {
      ElMessage({
        type: "success",
        message: res.data,
      });
      showRoleScope.value = false;
      reset();
      proxy.$refs.roleMenuForm.resetFields();
    }
  }
};
</script>

<style lang="less" scoped>
.table {
  position: relative;
  height: 520px;
  .pager {
    position: absolute;
    right: 0;
    bottom: -10px;
  }
}
.user-header {
  display: flex;
  justify-content: space-between;
  padding-bottom: -5px;
  padding-top: -10px;
}

.el-select {
  width: 196px;
  margin-right: 20px;
}

// 输入框宽度限制
.input_add {
  width: 196px;
  margin-right: 20px;
  &:hover {
    width: 196px;
  }
  &:focus {
    width: 196px;
  }
}
.end {
  justify-content: end;
  margin-bottom: 0px;
}
// .el-dropdown-link {
//   cursor: pointer;
//   align-items: center;
//   color: #409eff;
//   border: none;
//   outline: none;
// }

.tree-border {
  margin-top: 5px;
  border: 1px solid #e5e6e7;
  background: #ffffff none;
  border-radius: 4px;
  width: 380px;
}

.dialog-footer {
  display: flex;
  justify-content: end;
}
</style>
